import json
import re
from urllib.parse import parse_qs, urlparse

from bs4 import BeautifulSoup
from curl_cffi import requests
from flask import abort

from app.chatgpt.arkose import Arkose
from app.chatgpt.proofowork import ChatGPTPoW
from app.exceptions import ApiException
from app.utils.decorator import cache_func_data

user_agent =  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"



class AuthWeb:
    def __init__(self):
        # proxy = "http://plkkefqv:n773o7b6sg7n@38.154.227.167:5868"
        self.session = requests.Session()

        # self.session.proxies = {"http": proxy, "https": proxy}

        self.session.headers.update({
            "content-type": "application/x-www-form-urlencoded",
            "User-Agent": user_agent,
            "accept-language": "zh-CN,zh;q=0.9"
        })
        self.session.impersonate = 'safari'
        self.session.timeout = 10

    def set_arkose_token(self, blob_value):
        arkose_json = Arkose(user_agent).get_arkose_token(blob_value)
        #
        # # print(arkose_json["token"])
        # # if "sup=1" not in arkose_json["token"]:
        # #     raise ApiException("login web", "获取 arkoseToken 出错，待接入第三方打码平台")
        self.session.cookies.set('arkoseToken', arkose_json["token"])
        # res = requests.get("http://127.0.0.1:5006/token?method=login&token=" + blob_value)
        # print(res.json())
        # self.session.cookies.set('arkoseToken', res.json()["token"])



    def _login(self, username, password):
        url = "https://chatgpt.com/"

        home0_res = self.session.get(url)
        csrf_token = None
        if home0_res.cookies.get("__Host-next-auth.csrf-token"):
            csrf_token = home0_res.cookies["__Host-next-auth.csrf-token"]

        if not csrf_token:
            # csrf_token = "c5d5d68763754121f254d1ad591650613f99aba9a2efa5cc57809d19a063abb3%7C978aa6a11934a6b7f16b47d07320aa33bca6d75df5ab42fa2f80c32044c23d7e"
            # self.session.cookies.set("__Host-next-auth.csrf-token", csrf_token, secure=True)

            print("获取 csrf_token 出错")
            exit()

        match = re.search(r'"ua-(.*?)"', home0_res.text)
        device_id = match.group(1)

        # soup = BeautifulSoup(home0_res.text, 'html.parser')
        # # 查找 id="__NEXT_DATA__" 的 <script> 标签
        #
        # script_tag = soup.find('script', {'id': '__NEXT_DATA__'})
        # next_data = json.loads(script_tag.string)
        # device_id = next_data["props"]['pageProps']["user"]["id"].lstrip("ua-")

        login_url = self.get_login_url(device_id, csrf_token)
        identifier_res = self.session.get(login_url)
        self.session.headers.update({'referer': identifier_res.url})
        username_page_url = identifier_res.url

        # 输入账号
        identifier_query_params = parse_qs(urlparse(username_page_url).query)
        password_res = self.session.post(username_page_url, data={
            "state": identifier_query_params['state'][0],
            "username": username,
            "js-available": True,
            "webauthn-available": True,
            "is-brave": False,
            "webauthn-platform-available": True,
            "action": "default"
        })

        if password_res.status_code == 400:
            soup = BeautifulSoup(password_res.text, 'html.parser')
            err_span = soup.find('span', {'id': 'error-element-username'})
            abort(400, err_span.get_text().strip())

        # 获取 auth0-client-id
        pattern = re.compile(r'document\.cookie\s*=\s*`[^;]*auth0-client-id=([^;]+);')
        match = pattern.search(password_res.text)
        # print(password_res.status_code, password_res.text)
        auth0_client_id = match.group(1)
        self.session.cookies.set('auth0-client-id', auth0_client_id)
        self.session.cookies.set('oai-did', device_id)

        # 获取 data[blob] 并获取 arkose token
        pattern = re.compile(r"blob:\s*'(.+)'")
        match = pattern.search(password_res.text)
        blob_value = match.group(1)
        print("blob_value", blob_value)
        # self.set_arkose_token(blob_value)
        # set_sentinel_token(device_id)

        # 输入密码
        password_query_params = parse_qs(urlparse(password_res.url).query)
        self.session.headers.update({'referer': password_res.url})
        home1_res = self.session.post(password_res.url, data={
            "state": password_query_params['state'][0],
            "username": username,
            "password": password
        }, allow_redirects=False)

        if home1_res.status_code == 400:
            soup = BeautifulSoup(home1_res.text, 'html.parser')
            err_span = soup.find('span', {'id': 'error-element-password'})
            abort(400, err_span.get_text().strip())

        location1 = home1_res.headers['Location']
        location1_url = 'https://auth0.openai.com' + location1 if location1.startswith('/') else location1
        print("location1_url", location1_url)
        home2_res = self.session.get(location1_url, allow_redirects=False)

        location2 = home2_res.headers['Location']
        self.session.get(location2, allow_redirects=False)

        # print(self.session.get("https://chatgpt.com/api/auth/session").json())
        # print(home3_res.cookies["__Secure-next-auth.session-token"])
        # return home3_res.cookies["__Secure-next-auth.session-token"]

    @cache_func_data(cache_time=86400)
    def get_token_info(self, username, password):
        self._login(username, password)
        auth_info = self.session.get("https://chatgpt.com/api/auth/session").json()
        session_token = self.session.cookies.get("__Secure-next-auth.session-token")
        if not session_token:
            raise ApiException("login web", "login failed")

        return {
            "session_token": self.session.cookies.get("__Secure-next-auth.session-token"),
            "access_token": auth_info.get("accessToken")
        }

    def set_sentinel_token(self, device_id):
        chatgpt_pow = ChatGPTPoW()

        sentinel_res = self.session.post(
            "https://chatgpt.com/backend-api/sentinel/req",
            json={"id": device_id, "p": "gAAAAAC", "flow": "login"}
        )
        sentinel_json = sentinel_res.json()
        p = chatgpt_pow.get_answer({
            'seed': sentinel_json["proofofwork"]["seed"],
            'difficulty': sentinel_json["proofofwork"]["difficulty"],
            'user_agent': user_agent
        })
        sentinelToken = {"c": sentinel_json['token'], "p": p}
        self.session.cookies.set('sentinelToken', json.dumps(sentinelToken))

    def get_login_url(self, device_id, csrf_token):
        login_web_url = "https://chatgpt.com/api/auth/signin/login-web"
        params = {
            "prompt": "login",
            "screen_hint": "login",
            "ext-statsig-tier": "production",
            "ext-oai-did": device_id,
            "flow": "control"
        }
        data = {
            "callbackUrl": "/",
            "csrfToken": csrf_token.split("%7C")[0],
            "json": "true"
        }
        login_web_res = self.session.post(login_web_url, params=params, data=data)
        url = login_web_res.json()["url"]
        return url.replace("https://auth.openai.com", "https://auth0.openai.com")

    def __repr__(self):
        return self.__class__.__name__
